home *** CD-ROM | disk | FTP | other *** search
- ;-------------------------------------------------------------------------
- ; BOOT.SYS Illustrates some DOS device driver tricks.
- ;-------------------------------------------------------------------------
- ; This simple device driver will reboot the PC whenever an NMI is
- ; intercepted. This is convenient for folks with a Periscope breakout
- ; switch or an Atron probe. The IBM Professional Debugger package also
- ; included an NMI card, but the switch is on the card and not so convenient.
- ;
- ; This device driver could also be useful to a handicapped person where
- ; hitting Ctrl-Alt-Del is a difficult or impossible task depending on
- ; their keyboard layout.
- ;
- ; Many times a device driver will want to hook some vectors during init
- ; time and then not accept any I/O requests after that. All the work it
- ; does is in it's interrupt handler(s). The problem with this is that
- ; after init, the device is left with a larger DD interrupt routine than
- ; is needed if all it's going to do is reject all requests. By having the
- ; device's init code redirect the interrupt routine pointer in the device
- ; header to a shorter "mini" DD interrupt routine we can set the ending
- ; address of the device driver such that the larger initial interrupt
- ; routine is part of the code to be thrown away after initialization.
- ; This results results in smaller resident memory requirements for the
- ; device driver.
- ;
- ; By setting the symbol SAVE_MEMORY below to 0 or 1 the device driver can
- ; be built with or without the interrupt routine hack. On my development
- ; system running DR-DOS 6.0, the trick saved a paragraph of resident memory.
- ; Other device drivers may save a bit more.
- ;
- ; Another trick used below has to do with the name of the device. I always
- ; worry about character devices invading the name space that the DOS file
- ; system uses when writing a device like this one, which is never intended
- ; to do I/O. By having blanks at the start of the device name in the
- ; device header, we lessen the possibility of some DOS app stumbling across
- ; this device driver by accident.
- ;
- ; Yet another trick used below is to place a '$' right after the device
- ; header. This allows the string in the device header to be used to
- ; print the device name during initialization via Int 21 fn 9.
- ;-------------------------------------------------------------------------
- ; WARNING: This code WON'T WORK on systems that use NMI for normal system
- ; operation, like the PCjr and PC convertable.
- ;-------------------------------------------------------------------------
- ; Tony Ingenoso
- ; 1323 SE 17th #274
- ; Ft. Lauderdale, FL 33316
- ;-------------------------------------------------------------------------
-
- SAVE_MEMORY = 0
-
- ;----------------------------------------------
- ; Device driver request header structure
- ;----------------------------------------------
- request_header struc
- len db ?
- unit db ?
- command db ?
- status dw ?
- reserve db 8 dup (?)
- ;--- init specific ---
- nunits db ?
- endaddr dd ?
- request_header ends
-
- ;----------------------------------------------
- ; Dummy segment where the BIOS lives
- ;----------------------------------------------
- bios segment at 0FFFFH
- assume cs:bios
- org 0
- boot label far ; Jumping here reboots the PC
- bios ends
-
-
- cseg segment para public 'CODE'
- assume cs:cseg
- org 0
- ;------------- DEVICE HEADER ------------------
- dd -1 ; Link to next device
- dw 8000H ; Character device
- dw offset strategy ;
- intaddr dw offset interrupt; Initially point to large interrupt routine
- devname db ' BOOT','$' ; Blanks prevent stumbling on dev by accident
- ;----------------------------------------------
-
- req_ptr label dword ; Strat saves RQH pointer here
- rh_offset dw ?
- rh_seg dw ?
-
- ;----------------------------------------------
- ; NMI trapper routine
- ;----------------------------------------------
- NMItrapper proc far
- mov ax, 0040H ; Set BIOS reset flag
- mov ds, ax ;
- mov word ptr ds:[72H],1234H ; WARM
- jmp boot ; JMP FFFF:0000
- NMItrapper endp
-
- ;----------------------------------------------
- ; DD strat routine
- ;----------------------------------------------
- strategy proc far
- mov cs:rh_offset, bx ;offset
- mov cs:rh_seg, es ;segment
- ret
- strategy endp
-
- IF SAVE_MEMORY
- ;----------------------------------------------
- ; DD interrupt routine for post-INIT requests.
- ;----------------------------------------------
- ; Using this mini interrupt routine after init
- ; reduces the resident memory requirements of
- ; the device driver.
- ;----------------------------------------------
- mini_interrupt proc far
- push ds ;
- push si ;
- lds si, cs:req_ptr ; DS:SI-->request header
- mov [si].status, 8103H ; Status = Done + Error + Unk command
- pop si ;
- pop ds ;
- ret ;
- mini_interrupt endp
-
- THROW_AWAY_CODE label near
- ENDIF
-
- ;----------------------------------------------
- ; DD interrupt routine for INIT requests
- ;----------------------------------------------
- interrupt proc far
- push ds ; Save what gets whacked
- push si ;
- push ax ;
- lds si, cs:req_ptr ; DS:SI-->request header
- mov al, ds:[si].command ; AL == command code
- cmp al, 0 ; Is it an init request?
- jne error ; All but INIT get error
- call initialize ;
- mov ax, 0100H ; Status = No error + Done
- jmp short exit ;
- error: mov ax, 8103H ; Error + Done + Unknown command
- exit: mov ds:[si].status, ax ; Set status word in RQH.
- pop ax ; Restore
- pop si ;
- pop ds ;
- ret
- interrupt endp
-
- IF (SAVE_MEMORY EQ 0)
- THROW_AWAY_CODE label near
- ENDIF
- ;----------------------------------------------
- ; Initialize the device
- ;----------------------------------------------
- initialize proc near
- push dx ; Save DX
- push cs ; DS==CS
- pop ds ;
- assume ds:cseg
-
- IF SAVE_MEMORY
- ;
- ; Relocate the DD's interrupt routine to the "mini".
- ;
- mov word ptr intaddr, offset mini_interrupt
- ENDIF
-
- ;
- ; Display the logo message
- ;
- mov ah, 09H ; Display the logo
- mov dx, offset logo ;
- int 21H ;
- ;
- ; Grab the NMI vector.
- ;
- mov ax, 2502H ; NMI is Int 2
- mov dx, offset NMItrapper ;
- int 21H ;
- ;
- ; Show the name of the initializing device
- ;
- mov ah, 09H
- mov dx, offset devini1 ; Display "Device ["
- int 21H
- mov dx, offset devname ; Display the device name
- int 21H
- mov dx, offset devini2 ; Display "] initialized."
- int 21H
- ;
- ; Set the ending address.
- ;
- lds si, cs:req_ptr ; Get RQH pointer back
- assume ds:nothing
- mov word ptr [si].endaddr, offset THROW_AWAY_CODE
- mov word ptr [si].endaddr+2, cs
- pop dx ; Restore DX
- ret
- initialize endp
-
- ;----------------------------------------------
- ; Messages
- ;----------------------------------------------
- logo db 'BOOT V1.00, Reboot on NMI',13,10
- db 'Tony Ingenoso, 1992',13,10,'$'
-
- devini1 db 'Device [$'
- devini2 db '] initialized.',13,10,'$'
-
- cseg ends
- end
-